package service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"insighttracking/common/types"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"strings"
	"time"
)

type _mealService struct{}

var MealService = _mealService{}

func (s _mealService) CreateTemplateApi(ctx context.Context, enterpriseID int64, name string, describe string, startDate, endDate time.Time) (resp *model.MealsTemplateEntity, err error) {
	resp = &model.MealsTemplateEntity{
		EnterpriseID: enterpriseID,
		Name:         name,
		Describe:     describe,
		StartDate:    startDate,
		EndDate:      endDate,
	}
	err = dao.MealsTemplateEntity.WithContext(ctx).Create(resp)
	return
}

func (s _mealService) BatchCreateTemplateDetailApi(ctx context.Context, mealsModel []*model.MealsTemplateDetailEntity) (err error) {
	err = dao.MealsTemplateDetailEntity.WithContext(ctx).CreateInBatches(mealsModel, len(mealsModel))
	return
}

func (s _mealService) GetTemplateListApi(ctx context.Context, enterpriseID int64, name string) (resp []*model.MealsTemplateEntity, err error) {
	tx := dao.MealsTemplateEntity.WithContext(ctx).Where(dao.MealsTemplateEntity.EnterpriseID.Eq(enterpriseID))
	if name != "" {
		name = strings.ReplaceAll(name, "%", "\\%")
		name = strings.ReplaceAll(name, "_", "\\%")
		tx = tx.Where(dao.MealsTemplateEntity.Name.Like("%" + name + "%"))
	}
	return tx.Find()

}

func (s _mealService) GetByIDApi(ctx context.Context, id int64) (resp *model.MealsTemplateEntity, err error) {
	return dao.MealsTemplateEntity.WithContext(ctx).Where(dao.MealsTemplateEntity.ID.Eq(id)).First()
}

func (s _mealService) GetTemplateDetailListApi(ctx context.Context, id int64) (resp []*types.MealsDetail, err error) {
	resp = make([]*types.MealsDetail, 0)
	list, err := s.GetTemplateDetailApi(ctx, id)
	var allDishIDs []int64
	for _, item := range list {
		// 遍历各排餐的菜品，组合成切片
		var dishIDs []int64
		dishData := make([]*types.DishData, 0)
		err = json.Unmarshal([]byte(item.DishesIds), &dishIDs)
		allDishIDs = append(allDishIDs, dishIDs...)

		// 预设结构
		for _, dishID := range dishIDs {
			dishData = append(dishData, &types.DishData{
				ID: dishID,
			})
		}
		resp = append(resp, &types.MealsDetail{
			Date:     item.Date.Format("2006-01-02"),
			Type:     item.Type,
			Weekday:  item.Weekday,
			DishData: dishData,
		})
	}
	dishEntities, err := dao.DishesEntity.WithContext(ctx).Where(dao.DishesEntity.ID.In(allDishIDs...)).Find()
	dishIDDataMap := make(map[int64]*model.DishesEntity)
	for _, dishEntity := range dishEntities {
		if _, ok := dishIDDataMap[dishEntity.ID]; !ok {
			dishIDDataMap[dishEntity.ID] = dishEntity
		}
	}
	for _, item := range resp {
		for _, dishData := range item.DishData {
			if _, ok := dishIDDataMap[dishData.ID]; ok {
				dishData.Name = dishIDDataMap[dishData.ID].Name
				dishData.SalesPrice = dishIDDataMap[dishData.ID].SalesPrice
			}
		}
	}
	return
}

func (s _mealService) EditTemplateDetailApi(ctx context.Context, id int64, date time.Time, _type int64, weekday int64, dishedIDs string) (err error) {
	entity, err := dao.MealsTemplateDetailEntity.WithContext(ctx).Where(
		dao.MealsTemplateDetailEntity.MealsTemplateID.Eq(id),
		dao.MealsTemplateDetailEntity.Date.Eq(date),
		dao.MealsTemplateDetailEntity.Type.Eq(_type),
	).First()

	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = dao.MealsTemplateDetailEntity.WithContext(ctx).Create(&model.MealsTemplateDetailEntity{
			MealsTemplateID: id,
			Date:            date,
			Type:            _type,
			Weekday:         weekday,
			DishesIds:       dishedIDs,
		})
	} else {
		entity.DishesIds = dishedIDs
		err = dao.MealsTemplateDetailEntity.WithContext(ctx).Save(entity)
	}
	return err
}

func (s _mealService) EditTemplateApi(ctx context.Context, entity *model.MealsTemplateEntity) (err error) {
	return dao.MealsTemplateEntity.WithContext(ctx).Save(entity)
}

func (s _mealService) GetCustomerMealListApi(ctx context.Context, id int64, startDate, endDate time.Time) (resp []*types.MealsDetail, err error) {
	resp = make([]*types.MealsDetail, 0)
	list, err := dao.MealsCustomerEntity.WithContext(ctx).Where(
		dao.MealsCustomerEntity.CustomerID.Eq(id),
		dao.MealsCustomerEntity.Date.Gte(startDate),
		dao.MealsCustomerEntity.Date.Lte(endDate),
	).Order(dao.MealsCustomerEntity.Date.Asc()).Find()
	var allDishIDs []int64
	for _, item := range list {
		// 遍历各排餐的菜品，组合成切片
		var dishIDs []int64
		dishData := make([]*types.DishData, 0)
		err = json.Unmarshal([]byte(item.DishesIds), &dishIDs)
		allDishIDs = append(allDishIDs, dishIDs...)

		// 预设结构
		for _, dishID := range dishIDs {
			dishData = append(dishData, &types.DishData{
				ID: dishID,
			})
		}
		resp = append(resp, &types.MealsDetail{
			Date:     item.Date.Format("2006-01-02"),
			Type:     item.Type,
			Weekday:  item.Weekday,
			DishData: dishData,
		})
	}

	dishIDDataMap, err := DishService.GetDishInfoMapApi(ctx, allDishIDs)
	for _, item := range resp {
		for _, dishData := range item.DishData {
			if _, ok := dishIDDataMap[dishData.ID]; ok {
				dishData.Name = dishIDDataMap[dishData.ID].Name
				dishData.SalesPrice = dishIDDataMap[dishData.ID].SalesPrice
			}
		}
	}
	return
}

func (s _mealService) EditCustomerMealApi(ctx context.Context, id int64, date time.Time, _type int64, weekday int64, dishedIDs string) (err error) {
	entity, err := dao.MealsCustomerEntity.WithContext(ctx).Where(
		dao.MealsCustomerEntity.CustomerID.Eq(id),
		dao.MealsCustomerEntity.Date.Eq(date),
		dao.MealsCustomerEntity.Type.Eq(_type),
	).First()

	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = dao.MealsCustomerEntity.WithContext(ctx).Create(&model.MealsCustomerEntity{
			CustomerID: id,
			Date:       date,
			Type:       _type,
			Weekday:    weekday,
			DishesIds:  dishedIDs,
		})
	} else {
		entity.DishesIds = dishedIDs
		err = dao.MealsCustomerEntity.WithContext(ctx).Save(entity)
	}
	return err
}

func (s _mealService) TemplateApplyApi(ctx context.Context, tx *dao.QueryTx, entities []*model.MealsCustomerEntity) (err error) {
	for _, entity := range entities {
		err = tx.MealsCustomerEntity.WithContext(ctx).Save(entity)
		if err != nil {
			fmt.Println("mealsCustomerEntity.WithContext().Save(entity)", err)
			fmt.Println(err.Error())
		}
	}
	return
}

func (s _mealService) GetTemplateDetailApi(ctx context.Context, id int64) (resp []*model.MealsTemplateDetailEntity, err error) {
	return dao.MealsTemplateDetailEntity.WithContext(ctx).Where(dao.MealsTemplateDetailEntity.MealsTemplateID.Eq(id)).Order(dao.MealsTemplateDetailEntity.Date.Asc()).Find()
}

func (s _mealService) GetCustomerMealApi(ctx context.Context, customerID int64, date time.Time, _type int64) (resp []*model.MealsCustomerEntity, err error) {
	tx := dao.MealsCustomerEntity.WithContext(ctx).Where(
		dao.MealsCustomerEntity.CustomerID.Eq(customerID),
		dao.MealsCustomerEntity.Date.Eq(date),
	)
	if _type != 0 {
		tx.Where(dao.MealsCustomerEntity.Type.Eq(_type))
	}
	return tx.Find()
}
